package com.huarui.initial.service;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.ewaf.framework.model.ListModel;
import org.ewaf.framework.service.BaseService;
import org.ewaf.framework.util.BeanUtil;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;

import com.huarui.code.dao.ICodeGenericDao;
import com.huarui.code.model.CodeGeneric;
import com.huarui.department.dao.IDepartmentDao;
import com.huarui.department.model.Department;
import com.huarui.initial.dao.IInitialDao;
import com.huarui.initial.model.Initial;
import com.huarui.initial.util.InitialErrorsEnum;
import com.huarui.initial.util.InitialItemErrors;
import com.huarui.initial.util.InitialUtil;
import com.huarui.initial.util.InitialVO;
import com.huarui.initialItem.dao.IinitialItemDao;
import com.huarui.initialItem.model.InitialItem;
import com.huarui.part.dao.IPartDao;
import com.huarui.part.model.Part;
import com.huarui.store.dao.IStoreDao;
import com.huarui.store.model.Store;
import com.huarui.user.model.SessionMessage;
import com.huarui.user.security.UserHolder;
import com.huarui.util.PinyinToolkit;

/**
 * @author mircle
 */
public class InitialService extends BaseService {
	private final static Logger logger = Logger.getLogger(InitialService.class);
	private IinitialItemDao iInitialItemDao;
	private IPartDao iPartDao;
	private ICodeGenericDao iCodeGenericDao;
	private IStoreDao storeDao;
	private IDepartmentDao departmentDao;
	private IInitialDao getDao() {
		return (IInitialDao) dao;
	}

	/**
	 * 将用户的零件excel数据导入数据库,生成 期初单
	 * 
	 * @param itemList
	 */
	@SuppressWarnings("unchecked")
	public Map<String,Object> excelDataToDB(final SessionMessage sm,final Integer initailId,final File excel) {
		/*POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(excel));
		HSSFWorkbook wb = new HSSFWorkbook(fs);
		wb*/
		final Map<String,Object> resultMap=new HashMap<String, Object>();
		 transactionTemplate.execute(new TransactionCallback() {
			@Override
			public Object doInTransaction(TransactionStatus status) {
				Map<String,Object> paramsMap=new HashMap<String, Object>();
				paramsMap.put("id", initailId);
				paramsMap.put("companyId", sm.getCompanyId());
				paramsMap.put("isLock", true);
				Initial initial = null;
				if(initailId==null){
					initial = createInitial(sm);
				}else{
					initial = (Initial) getDao().getById(paramsMap);
				}
				try {
					readExcel(initial,excel);				
				} catch (Exception e) {
					logger.error("期初单上传excel出错",e);
					resultMap.put(InitialErrorsEnum.SUCCESS.getMsg(), InitialErrorsEnum.ERROR_MSG_EXCEL.getMsg());
					status.setRollbackOnly();
					return resultMap;
				}
				if(initailId==null){
					paramsMap.clear();
					paramsMap.put("id",initial.getId());
					paramsMap.put("companyId", sm.getCompanyId());
					resultMap.put("data", getDao().getInitialByCondition(paramsMap));
				}
				resultMap.put(InitialErrorsEnum.SUCCESS.getMsg(),InitialErrorsEnum.RESULT_TYPE_SUCCESS.getMsg());
				return null;
			}
		});
		
		return resultMap;
	}
	public BigDecimal excelSave(Initial initial,List<InitialItem> itemList,Map<String,Map> storeListMap){
		// 总金额
		if(itemList.size()<1)return BigDecimal.ZERO;
		BigDecimal amount = BigDecimal.ZERO;
		//获得所有item表零件的part记录
		Map<String,Object> map = new HashMap<String,Object>();
		map.put("initialItemList", itemList);
		List<Part> partList= iPartDao.getPartListByConditions(map);	
		Map<String,Part> partMap=new HashMap<String,Part>();

		for(Part part:partList){
			partMap.put(part.getCode()+part.getSource(),part);
		}
		for (InitialItem initialItem : itemList) {
			Part part= partMap.get(initialItem.getCode()+initialItem.getSource());
			amount = amount.add(InitialUtil.calAmout(initialItem));
			if (part != null) {
				initialItem.setPartId(part.getId());
				initialItem.setName(part.getName());
				initialItem.setNameEn(part.getNameEn());
				initialItem.setMeasurementUnit(part.getMeasurementUnit());
				initialItem.setPartCategoryId(part.getPartCategoryId());
				initialItem.setLevel1Name(part.getLevel1Name());
				initialItem.setLevel2Name(part.getLevel2Name());
				initialItem.setLevel1Id(part.getLevel1Id());
				initialItem.setCostAmount(InitialUtil.calAmout(initialItem));
			}
			initialItem.setInitialId(initial.getId());
			InitialItemErrors.setErrorsProperty(initialItem);
		}
		iInitialItemDao.batchInsert(itemList);
		return amount;
	}

	private List<Integer> getErrorTypeList(Object... T) {
		List<Integer> errorTypeList = new ArrayList<Integer>();
		for (int i = 0; i < T.length; i++) {
			errorTypeList.add((Integer) T[i]);
		}
		return errorTypeList;
	}

	public Initial createInitial(SessionMessage sm) {
		Initial initial = new Initial();
		return createInitial(sm,initial);
	}
	public Initial createInitial(SessionMessage sm,Initial initial) {
		initial.setAmount(BigDecimal.ZERO);
		initial.setCompanyId(sm.getCompanyId());
		initial.setCreatorId(sm.getUserId());
		initial.setCode(iCodeGenericDao.getNewCode(sm.getCompanyId(), "initial"));
		//initial.setGmtCreate(new Date());
		initial.setStatus(0);
		initial.setCurrentorId(sm.getUserId());
		getDao().create(initial);
		return initial;
	}

	@SuppressWarnings("unchecked")
	public Map<String,Object> getInitialCountByCondition(SessionMessage sm, ListModel lm,Map<String,Object> map) {
		Map<String,Object> resultMap = new HashMap<String, Object>();
		try {
			map.put("companyId", sm.getCompanyId());
			int count=this.getDao().getInitialCountByCondition(map);
			map.put("listModel", lm);
			List<InitialVO> resList = this.getDao().getInitialListByCondition(map);
			resultMap.put("root", resList);
			resultMap.put("totalProperty",count);
		
		} catch (Exception e) {
			logger.error("期初列表查询出错", e);
		}
		return resultMap;
	}

	public void create(SessionMessage sm, Initial initial) {
		initial.setAmount(new BigDecimal(0));
		initial.setCompanyId(sm.getCompanyId());
		initial.setCode(iCodeGenericDao.getNewCode(sm.getCompanyId(),
				CodeGeneric.INITIAL));
		initial.setCreatorId(sm.getUserId());
		initial.setCurrentorId(sm.getUserId());
		initial.setStatus(0);
		initial.setGmtCreate(new Date());
		this.getDao().create(initial);
	}
	public Map<String,Object> getInitialVOById(Integer id,SessionMessage sm) {
		Map<String,Object> resultMap=new HashMap<String, Object>();
		Map<String,Object> map=new HashMap<String, Object>();
		map.put("id", id);
		map.put("companyId", sm.getCompanyId());
		try {
			InitialVO vo = getDao().getInitialByCondition(map);
			resultMap.put("data", vo);
		} catch (Exception e) {
			logger.error("根据id获得initial出错",e);
			resultMap.put(InitialErrorsEnum.SUCCESS.getMsg(),InitialErrorsEnum.ERROR_MSG_DATABASE.getMsg());
			return resultMap;
		}
		resultMap.put("userId", sm.getUserId());
		resultMap.put(InitialErrorsEnum.SUCCESS.getMsg(), InitialErrorsEnum.RESULT_TYPE_SUCCESS.getMsg());
		return resultMap;
	}

	/**
	 * 删除主表id为id的记录且删除initialItem表对应的记录
	 * 
	 * @param initialId
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public Map<String,Object> delete(final Integer id,final SessionMessage sm) {
		Map<String,Object> resultMap=(Map<String, Object>) transactionTemplate.execute(new TransactionCallback() {
			Map<String,Object> resultMap=new HashMap<String, Object>();
			@Override
			public Object doInTransaction(TransactionStatus status) {
				try {
					Map map=new HashMap();
					map.put("id", id);
					map.put("companyId", sm.getCompanyId());
					map.put("currentorId", sm.getUserId());
					int rows=getDao().deleteInitialById(map);
					if(rows==0){
						resultMap.put(InitialErrorsEnum.SUCCESS.getMsg(),InitialErrorsEnum.ERROR_MSG_RECORD_NOTEXT.getMsg());
						status.isRollbackOnly();
						return resultMap;
					}
					map.clear();
					map.put("initialId", id);
					iInitialItemDao.deleteByCondition(map);				
				} catch (Exception e) {
					logger.error("删除initial单错误",e);
					resultMap.put(InitialErrorsEnum.SUCCESS.getMsg(),InitialErrorsEnum.ERROR_MSG_DATABASE.getMsg());
					status.setRollbackOnly();
					return resultMap;
				}
				resultMap.put(InitialErrorsEnum.SUCCESS.getMsg(),InitialErrorsEnum.RESULT_TYPE_SUCCESS.getMsg());
				return resultMap;
			}
		});
		return resultMap;
	}

	public Map<String,Object> getCountErrorsByInitialId(Integer initialId,SessionMessage sm) {
		Map<String,Object> resultMap=new HashMap<String,Object>();
		try {
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("initialId", initialId);
			map.put("errorTypeList",getErrorTypeList(InitialItem.ERRORTYPE_ERROR));
			Integer errorCount = iInitialItemDao.countErrors(map);
			resultMap.put("errorCount", errorCount);
			map.remove("errorTypeList");
			map.put("errorTypeList",getErrorTypeList(InitialItem.ERRORTYPE_WARN));
			Integer warnCount = iInitialItemDao.countErrors(map);
			resultMap.put("warnCount", warnCount);
			map.remove("errorTypeList");
			map.put("errorTypeList",getErrorTypeList(InitialItem.ERRORTYPE_CORRECT));
			Integer correctCount = iInitialItemDao.countErrors(map);
			resultMap.put("correctCount", correctCount);
		} catch (Exception e) {
			logger.error("initial获取错误信息出错",e);
			resultMap.put(InitialErrorsEnum.SUCCESS.getMsg(), InitialErrorsEnum.ERROR_MSG_DATABASE.getMsg());
			return resultMap;
		}
		resultMap.put(InitialErrorsEnum.SUCCESS.getMsg(), InitialErrorsEnum.RESULT_TYPE_SUCCESS.getMsg());
		return resultMap;
	}
	/**
	 * 释放单据
	 */
	@SuppressWarnings("unchecked")
	public Map<String,Object> release(final Integer initialId,final SessionMessage sm){
		Map<String,Object> resultMap=(Map<String, Object>) transactionTemplate.execute(new TransactionCallback() {	
			Map<String,Object> resultMap=new HashMap<String,Object>();
			@Override
			public Object doInTransaction(TransactionStatus status) {
				try{
					Map<String,Object> map=new HashMap<String,Object>();
					map.put("id",initialId);
					map.put("companyId", sm.getCompanyId());
					map.put("isLock", true);
					Initial initial = (Initial)getDao().getById(map);
					initial.setCurrentorId(null);
					getDao().update(initial);
				}catch(Exception e){
					logger.error("释放initial单据出错",e);
					resultMap.put(InitialErrorsEnum.SUCCESS.getMsg(), InitialErrorsEnum.ERROR_MSG_DATABASE.getMsg());
					status.setRollbackOnly();
					return resultMap;
				}
				resultMap.put(InitialErrorsEnum.SUCCESS.getMsg(), InitialErrorsEnum.RESULT_TYPE_SUCCESS.getMsg());
				return resultMap;
			}
		});
		return resultMap;
	}
	/**
	 * 接手单据
	 */
	@SuppressWarnings("unchecked")
	public Map<String,Object> receive(final Integer initialId,final SessionMessage sm){
		Map<String,Object> reslutMap=(Map<String, Object>) transactionTemplate.execute(new TransactionCallback() {			
			Map<String,Object> resultMap=new HashMap<String, Object>();
			@Override
			public Object doInTransaction(TransactionStatus status) {
				try {
					Map map=new HashMap();
					map.put("id",initialId);
					map.put("companyId", sm.getCompanyId());
					map.put("isLock", true);
					Initial initial = (Initial) getDao().getById(map);
					initial.setCurrentorId(sm.getUserId());
					getDao().update(initial);
				} catch (Exception e) {
					logger.error("接手initail单据错误:",e);
					resultMap.put(InitialErrorsEnum.RESULT_TYPE_SUCCESS.getMsg(), InitialErrorsEnum.ERROR_MSG_DATABASE.getMsg());
					status.setRollbackOnly();
					return resultMap;
				}
				resultMap.put(InitialErrorsEnum.SUCCESS.getMsg(), InitialErrorsEnum.RESULT_TYPE_SUCCESS.getMsg());
				return resultMap;
			}
		});	
		return reslutMap;
	}
	/**
	 * 保存单据
	 */
	@SuppressWarnings("unchecked")
	public Map<String,Object> save(final Initial initialtemp,final SessionMessage sm){
		Map<String,Object> resultMap=(Map<String, Object>) transactionTemplate.execute(new TransactionCallback() {
			Map<String,Object> resultMap=new HashMap<String, Object>();
			@Override
			public Object doInTransaction(TransactionStatus status) {
				try {
					Map<String,Object> map=new HashMap<String, Object>();
					map.put("id", initialtemp.getId());
					map.put("companyId", sm.getCompanyId());
					map.put("isLock", true);
					Initial initial = (Initial) getDao().getById(map);
					initial.setMemo(initialtemp.getMemo());
					initial.setGmtAccept(initialtemp.getGmtAccept());
					getDao().update(initial);
				} catch (Exception e) {
					logger.error("initial保存单据错误",e);
					status.setRollbackOnly();
					resultMap.put(InitialErrorsEnum.SUCCESS.getMsg(), InitialErrorsEnum.ERROR_MSG_DATABASE.getMsg());
				}
				resultMap.put(InitialErrorsEnum.SUCCESS.getMsg(), InitialErrorsEnum.RESULT_TYPE_SUCCESS.getMsg());
				return resultMap;
			}
		});
		return resultMap;
	}
	@SuppressWarnings("unchecked")
	public BigDecimal getTotalMountByConditions(Map map) {
		return this.getDao().getTotalMountByConditions(map);
	}

	/**
	 * 读取excel
	 * 
	 * @param excelFile
	 * @return
	 * @throws IOException 
	 * @throws FileNotFoundException 
	 */
	@SuppressWarnings("deprecation")
	private BigDecimal readExcel(Initial initial,File excel) throws FileNotFoundException, IOException {
		int eachNum=500;
		BigDecimal amount=initial.getAmount();
		Map<String,Map> storeListMap=getStoreList();
		List<InitialItem> itemList = new ArrayList<InitialItem>();
			POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(excel));
			HSSFWorkbook wb = new HSSFWorkbook(fs);
			int sn = wb.getNumberOfSheets();
			for (int i = 0; i < 1; i++) {
				HSSFSheet sheet = wb.getSheetAt(i);
				for (int j = 1; j <= sheet.getLastRowNum(); j++) {
					HSSFRow row = sheet.getRow(j);
					InitialItem item = new InitialItem();
					for (int k = 0; k < row.getLastCellNum(); k++) {
						HSSFCell cell = row.getCell((short)k);
						if(cell==null)continue;
						if (k == 0){

							item.setCode(cell.getRichStringCellValue()
									.toString());
						}
						if (k == 1) {
							item.setSource(Double.valueOf(
									cell.getNumericCellValue()).intValue());
						} 
						if (k == 2) {
							item.setBrand(cell.getRichStringCellValue()
									.toString());
						}
						if (k == 3) {
							item.setCarModel(cell.getRichStringCellValue()
									.toString());
						}
						if (k == 4) {
							item.setOrigin(cell.getRichStringCellValue()
									.toString());
						}
						if(k==5){
							item.setCost(new BigDecimal(cell.getNumericCellValue()));
						}
						if (k == 6) {
							item.setRetailPrice(new BigDecimal(cell
									.getNumericCellValue()));
						}
						if(k==7){
							item.setMinPrice(new BigDecimal(cell.getNumericCellValue()));
						}
						if (k == 8) {
							item.setQuantity(Double.valueOf(
									cell.getNumericCellValue()).intValue());
						}
						if(k==9){
							item.setMinOnHand(Double.valueOf(
									cell.getNumericCellValue()).intValue());
						}
						if(k==10){
							item.setMaxOnHand(Double.valueOf(
									cell.getNumericCellValue()).intValue());
						}
						if (k == 11) {
							item.setSwapCode(cell.getRichStringCellValue().toString());
						}
						if (k == 12) {
							Map store=null;
							if(cell.getRichStringCellValue().toString()==null||cell.getRichStringCellValue().toString().equals("")){
								for(Iterator it=storeListMap.entrySet().iterator();it.hasNext();){
									Map.Entry e=(Entry) it.next();
									Map obj=(Map) e.getValue();
									Integer isDefault=(Integer) obj.get("isDefault");
									if(isDefault==1){
										store=obj;
										break;
									}
								}
							}else{
								store=storeListMap.get(cell.getRichStringCellValue().toString());
							}
							if(store==null){
								Store s=createStore(cell.getRichStringCellValue().toString(),storeListMap);
								item.setStoreName(s.getName());
								item.setStoreId(s.getId());
							}else{
								item.setStoreName((String)store.get("name"));
								item.setStoreId((Integer)store.get("id"));
							}
						}
						if(k==13){
							item.setShelf(cell.getRichStringCellValue().toString());
						}
						
						if(k==14){
							item.setTempName(cell.getRichStringCellValue().toString());
						}
					}
					if(item.getCode()!=null&&!"".equals(item.getCode())){
						itemList.add(item);
					}
					if(itemList.size()==eachNum){
						amount=amount.add(excelSave(initial, itemList,storeListMap));
						itemList.clear();
					}
					if(sheet.getLastRowNum()==j){
						amount=amount.add(excelSave(initial, itemList,storeListMap));
						itemList.clear();
					}
				}
			}		
		initial.setAmount(amount);
		getDao().update(initial);
		return amount;
	}

	@SuppressWarnings("unchecked")
	private Map<String,Map> getStoreList() {
		Map<String,Object> map=new HashMap<String, Object>();
		SessionMessage sm=UserHolder.getCurrentSessionMessage();
		map.put("companyId", sm.getCompanyId());
		List<Map> storeList=storeDao.getStoresByConditions(map);
		Map<String,Map> result=new HashMap<String, Map>();
		for(Map temp:storeList){
			result.put((String)temp.get("name"), temp);
		}
		return result;
	}
	@SuppressWarnings("unchecked")
	private Department getDepartmentByCompanyId(Integer companyId){
		Department department=departmentDao.getByisDefault(companyId);
		return department;
	}
	private Store createStore(String name,Map map){
		SessionMessage sm=UserHolder.getCurrentSessionMessage();
		Department department=getDepartmentByCompanyId(sm.getCompanyId());
		Store store=new Store();
		store.setName(name);
		store.setDepartmentId(department.getId());
		store.setDepartmentName(department.getName());
		store.setCompanyId(sm.getCompanyId());
		store.setPyCode(PinyinToolkit.cn2FirstSpell(name));
		storeDao.create(store);
		Map storeMap=new HashMap();
		BeanUtil.populateMap(storeMap, store);
		map.put(store.getName(),storeMap);
		return store;
	}
	public void setiInitialItemDao(IinitialItemDao iInitialItemDao) {
		this.iInitialItemDao = iInitialItemDao;
	}

	public void setiPartDao(IPartDao iPartDao) {
		this.iPartDao = iPartDao;
	}

	public void setiCodeGenericDao(ICodeGenericDao iCodeGenericDao) {
		this.iCodeGenericDao = iCodeGenericDao;
	}

	public void setStoreDao(IStoreDao storeDao) {
		this.storeDao = storeDao;
	}

	public void setDepartmentDao(IDepartmentDao departmentDao) {
		this.departmentDao = departmentDao;
	}
	
}
